home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / AETEGizmo ƒ / AppleEventUtilities.cp < prev    next >
Text File  |  1998-06-21  |  77KB  |  2,265 lines

  1. /*
  2.     File:        AppleEventUtilities.cp
  3.  
  4.     Contains:    C++ Wrappers for Apple Event manager
  5.  
  6. */
  7.  
  8. #ifndef __APPLEEVENTUTILITIES__
  9. #include "AppleEventUtilities.h"
  10. #endif
  11.  
  12. #ifndef __ASREGISTRY__
  13. #include <ASRegistry.h>
  14. #endif
  15.  
  16. #ifndef __OSUTILS__
  17. #include <OSUtils.h>
  18. #endif
  19.  
  20. #ifndef __SCRIPT__
  21. #include <Script.h>
  22. #endif
  23.  
  24. #ifndef __APPLEEVENTS__
  25. #include <AppleEvents.h>
  26. #endif
  27.  
  28. #ifndef __AEOBJECTS__
  29. #include <AEObjects.h>
  30. #endif
  31.  
  32. #ifndef __ALIASES__
  33. #include <Aliases.h>
  34. #endif
  35.  
  36. #ifndef __AEOBJECTPACKING__
  37. #include <AEPackObject.h>
  38. #endif
  39.  
  40. #ifndef __AEREGISTRY__
  41. #include <AERegistry.h>
  42. #endif
  43.  
  44. #ifndef __GESTALT__
  45. #include <Gestalt.h>
  46. #endif
  47.  
  48. //
  49. // Needed only by TAEvent::Ask
  50. //
  51. #ifndef __FUTURES__
  52. #include "Futures.h"
  53. #endif
  54.  
  55. #include    "stdarg.h"
  56. #include    "AEBuild.h"
  57.  
  58.     inline    void
  59. FailErr(    OSErr    err )
  60. {    if( err )
  61.         throw( err ); }
  62.  
  63. MakeTokenDescriptorProcPtr gNullContainerCreationProc = nil;
  64. ProcessDescriptorProcPtr gPreResolveProc = nil;
  65. MergeTokensProcPtr gMergeTokensProc = nil;
  66.  
  67. short TDescriptor::fCallbackFlags = kAEIDoMinimum;
  68.  
  69. //----------------------------------------------------------------------------------------
  70. // InstallNullContainerCreationProc: 
  71. //
  72. // The null container creation proc is used by TDescriptor::Resolve whenever it receives
  73. // a null descriptor to resolve.  This function is used to create a token for the null
  74. // container.
  75. //----------------------------------------------------------------------------------------
  76. void InstallNullContainerCreationProc(MakeTokenDescriptorProcPtr creationProc)
  77.     {
  78.     gNullContainerCreationProc = creationProc;
  79.     } // InstallNullContainerCreationProc 
  80.  
  81. //----------------------------------------------------------------------------------------
  82. // InstallPreResolveProc: 
  83. //
  84. // The PreResolveProc is called by TDescriptor::Resolve before it actually calls
  85. // AEResolve.  This allows special procs to handle things not understood by AEResolve
  86. // (alias records, for example).
  87. //----------------------------------------------------------------------------------------
  88. void InstallPreResolveProc(ProcessDescriptorProcPtr preResolveProc)
  89.     {
  90.     gPreResolveProc = preResolveProc;
  91.     } // InstallPreResolveProc 
  92.  
  93. //----------------------------------------------------------------------------------------
  94. // InstallMergeTokensProc: 
  95. //
  96. // The MergeTokensProc is called by TTokenDescriptor::AdoptToken whenever it needs to add
  97. // a token object to any token descriptor that already contains a token.  The merge token
  98. // proc is provided with two TAbstractScriptableObject*'s; it must return a
  99. // TAbstractScriptableObject* that has adopted the two tokens passed to it.
  100. //----------------------------------------------------------------------------------------
  101. void InstallMergeTokensProc(MergeTokensProcPtr mergeTokensProc)
  102.     {
  103.     gMergeTokensProc = mergeTokensProc;
  104.     } // InstallMergeTokensProc 
  105.  
  106. //----------------------------------------------------------------------------------------
  107. // CreateNullContainerToken: 
  108. //----------------------------------------------------------------------------------------
  109. TTokenDescriptor CreateNullContainerToken()
  110.     {
  111.     TTokenDescriptor nullContainer;
  112.     
  113.     if(gNullContainerCreationProc != nil)
  114.         nullContainer = (*gNullContainerCreationProc)();
  115.     
  116.     return nullContainer;
  117.     } // CreateNullContainerToken 
  118.  
  119. //========================================================================================
  120. // CLASS TDescriptor
  121. //
  122. // Class TDescriptor is a wrapper class for AEDesc objects.
  123. //========================================================================================
  124.  
  125.  
  126. //----------------------------------------------------------------------------------------
  127. // TDescriptor::Dispose:
  128. //
  129. // Disposed of the descriptor and the data stored inside it.
  130. //----------------------------------------------------------------------------------------
  131. void TDescriptor::Dispose()
  132.     {
  133.     FailErr(AEDisposeDesc(*this));
  134.     } // TDescriptor::Dispose 
  135.  
  136. //----------------------------------------------------------------------------------------
  137. // TDescriptor::AttemptCoercion:
  138. //
  139. // Try to coerce the type of the descriptor to something else.  This method will
  140. // NOT fail if the coercion could not be done.
  141. //----------------------------------------------------------------------------------------
  142. OSErr TDescriptor::AttemptCoercion(DescType typeToCoerceTo)
  143.     {
  144.     OSErr err = noErr;
  145.     
  146.     if(this->DescriptorType() != typeToCoerceTo)
  147.         {
  148.         TDescriptor tempDescriptor;
  149.         
  150.         // If AECoerceDesc returns a non-zero result code, then
  151.         // tempDescriptor will be typeNull, and we don't need to
  152.         // worry about disposing of it.
  153.         err = AECoerceDesc(*this,typeToCoerceTo,(AEDesc*)&tempDescriptor);
  154.  
  155.         if(err == noErr) {
  156.             try {
  157.                 Handle initialHandle = this->DataHandle();
  158.                 Handle coercedHandle = tempDescriptor.DataHandle();
  159.                 
  160.                 //
  161.                 // If doing a coerce-in-place, try to do a SetHandleSize
  162.                 // and then a BlockMove so that we end up using the same
  163.                 // handle when we exit as we had when we entered.  To do
  164.                 // otherwise is to invite double-dispose/memory leak problems
  165.                 // if some other peice of code still has a reference to
  166.                 // the descriptor before it was coerced
  167.                 //
  168.                 if((initialHandle != nil) && (coercedHandle != nil))
  169.                     {
  170.                     Size coercedSize = GetHandleSize(coercedHandle);
  171.                     SetHandleSize(initialHandle, coercedSize);
  172.                     FailErr(MemError());
  173.                     BlockMove(*coercedHandle, *initialHandle, coercedSize);
  174.                     this->fDescriptorType = tempDescriptor.DescriptorType();
  175.                     tempDescriptor.Dispose();
  176.                     }
  177.                 //
  178.                 // There are a couple of rare cases (typeTrue and typeFalse)
  179.                 // where the data handle is nil
  180.                 //
  181.                 else
  182.                     {
  183.                     //
  184.                     // It's undesirable to go from a nil-handle to a non-nil
  185.                     // handle, or visa-versa.  Don't do it.  Use 'Coerce'
  186.                     // rather than 'CoerceInPlace' if this is necessary.
  187.                     //
  188.                     if((initialHandle != nil) || (coercedHandle != nil))
  189.                         DebugStr("\pPotentially undesirable coerce-in-place");
  190.                     //
  191.                     // Try to dispose of the old descriptor (ignoring errors)
  192.                     // and then plug in the values from the coerced descriptor
  193.                     //
  194.                     AEDisposeDesc(*this);
  195.                     this->AdoptDesc(tempDescriptor);
  196.                     }
  197.                 }
  198.             catch( OSErr err )
  199.                 {
  200.                 tempDescriptor.Dispose();
  201.                 }
  202.             }
  203.         }
  204.     
  205.     return err;
  206.     } // TDescriptor::AttemptCoercion 
  207.  
  208. //----------------------------------------------------------------------------------------
  209. // TDescriptor::CoerceInPlace:
  210. //
  211. // Require that this object be coerced to the specified data type.  This method will
  212. // fail if the coercion does not work.
  213. //----------------------------------------------------------------------------------------
  214. void TDescriptor::CoerceInPlace(DescType typeToCoerceTo)
  215.     {
  216.     FailErr(this->AttemptCoercion(typeToCoerceTo));
  217.     } // TDescriptor::CoerceInPlace 
  218.  
  219. //----------------------------------------------------------------------------------------
  220. // TDescriptor::Coerce:
  221. //
  222. // Require that this object be coerced to the specified data type.  This method will
  223. // fail if the coercion does not work.
  224. //----------------------------------------------------------------------------------------
  225. TDescriptor TDescriptor::Coerce(DescType typeToCoerceTo) const
  226.     {
  227.     TDescriptor coercedDescriptor;
  228.     
  229.     FailErr(AECoerceDesc(*this,typeToCoerceTo,coercedDescriptor));
  230.     
  231.     return coercedDescriptor;
  232.     } // TDescriptor::Coerce 
  233.     
  234. //----------------------------------------------------------------------------------------
  235. // TDescriptor::CoerceToStandardType:
  236. //
  237. // This method attempts to coerce its data into some form of standard type
  238. // (e.g. typeChar or typeLongInteger).  It is really annoying that someone can
  239. // invent yet another data type that is coercable to text or as a long integer,
  240. // but we wouldn't have any way to know that such a coercion should be attempted.
  241. // typeMagnitude and typeEnumeration could throw us for a loop too.
  242. //
  243. // ••• In short, I really hate this routine, but I'm not sure what else to do about it.
  244. //----------------------------------------------------------------------------------------
  245. void TDescriptor::CoerceToStandardType()
  246.     {
  247.     switch(this->DescriptorType())
  248.         {
  249.         case typeAEText:
  250.         case typeIntlText:
  251.         case typeStyledText:
  252.             {
  253.             this->CoerceInPlace(typeChar);
  254.             break;
  255.             }
  256.         
  257.         case typeShortInteger:
  258.             {
  259.             this->CoerceInPlace(typeLongInteger);
  260.             break;
  261.             }
  262.         }
  263.     } // TDescriptor::CoerceToStandardType 
  264.     
  265. //----------------------------------------------------------------------------------------
  266. // TDescriptor::Clone:
  267. //
  268. // Return an exact copy of this descriptor
  269. //----------------------------------------------------------------------------------------
  270. TDescriptor TDescriptor::Clone() const
  271.     {
  272.     TDescriptor clonedDescriptor;
  273.     
  274.     FailErr(AEDuplicateDesc(*this, (AEDesc*)&clonedDescriptor));
  275.     
  276.     return clonedDescriptor;
  277.     } // TDescriptor::Clone 
  278.  
  279. //----------------------------------------------------------------------------------------
  280. // TDescriptor::CopyDesc: 
  281. //----------------------------------------------------------------------------------------
  282. void TDescriptor::CopyDesc(const TDescriptor& desc)
  283.     {
  284.     FailErr(AEDuplicateDesc((AEDesc*)&desc, *this));
  285.     } // TDescriptor::CopyDesc 
  286.  
  287. //----------------------------------------------------------------------------------------
  288. // TDescriptor::AdoptDesc: 
  289. //----------------------------------------------------------------------------------------
  290. void TDescriptor::AdoptDesc(TDescriptor& desc)
  291.     {
  292.     //
  293.     // It would be very tempting to set 'desc' to the null descriptor now
  294.     // that we have adopted it here.  That would be a bad idea, though, because
  295.     // we might intend this descriptor to actually be just a reference to
  296.     // the adopted desc, and not actually the new 'owner' of the data.
  297.     //
  298.     this->AdoptHandle(desc.DescriptorType(), desc.DataHandle());
  299.     } // TDescriptor::AdoptDesc 
  300.  
  301. //----------------------------------------------------------------------------------------
  302. // TDescriptor::CreateList:
  303. //
  304. // Create an empty descriptor list or AERecord with factored data.
  305. //
  306. // n.b.    It is better to call MakeList, MakeEmptyList or MakeAERecord rather than
  307. // using TDescriptor::CreateList directly.
  308. //----------------------------------------------------------------------------------------
  309. void TDescriptor::CreateList(Boolean isRecord, Ptr factoringPtr, Size factoredSize)
  310.     {
  311.     FailErr(AECreateList(factoringPtr, factoredSize, isRecord, *this));
  312.     } // TDescriptor::CreateList 
  313.  
  314. //----------------------------------------------------------------------------------------
  315. // TDescriptor::MakeNull: 
  316. //----------------------------------------------------------------------------------------
  317. void TDescriptor::MakeNull()
  318.     {
  319.     this->AdoptHandle(typeNull, nil);
  320.     } // TDescriptor::MakeNull 
  321.  
  322. //----------------------------------------------------------------------------------------
  323. // TDescriptor::AdoptHandle:
  324. //
  325. // Assign some data and a type directly to the descriptor
  326. //----------------------------------------------------------------------------------------
  327. void TDescriptor::AdoptHandle(DescType dataType, Handle dataHandle)
  328.     {
  329.     fDescriptorType = dataType;
  330.     fDataHandle = dataHandle;
  331.     } // TDescriptor::AdoptHandle
  332.  
  333. //----------------------------------------------------------------------------------------
  334. // TDescriptor::CopyData: 
  335. //----------------------------------------------------------------------------------------
  336. void TDescriptor::CopyData(const DescType typeCode, const Ptr data, const Size length)
  337.     {
  338.     FailErr(AECreateDesc(typeCode, data, length, *this));
  339.     } // TDescriptor::CopyData 
  340.  
  341. //----------------------------------------------------------------------------------------
  342. // TDescriptor::MakeBoolean: 
  343. //----------------------------------------------------------------------------------------
  344. void TDescriptor::MakeBoolean(const Boolean data)
  345.     {
  346.     this->CopyData(typeBoolean, (Ptr)&data, sizeof(Boolean));
  347.     } // TDescriptor::MakeBoolean 
  348.     
  349. //----------------------------------------------------------------------------------------
  350. // TDescriptor::MakeLong: 
  351. //----------------------------------------------------------------------------------------
  352. void TDescriptor::MakeLong(const long data)
  353.     {
  354.     this->CopyData(typeLongInteger, (Ptr)&data, sizeof(long));
  355.     } // TDescriptor::MakeLong
  356.  
  357. //----------------------------------------------------------------------------------------
  358. // TDescriptor::MakeUnsignedLong: 
  359. //----------------------------------------------------------------------------------------
  360. void TDescriptor::MakeUnsignedLong(const unsigned long data)
  361.     {
  362.     this->CopyData(typeMagnitude, (Ptr)&data, sizeof(unsigned long));
  363.     } // TDescriptor::MakeUnsignedLong
  364.  
  365. //----------------------------------------------------------------------------------------
  366. // TDescriptor::MakeEnumeration: 
  367. //----------------------------------------------------------------------------------------
  368. void TDescriptor::MakeEnumeration(const DescType enumeration)
  369.     {
  370.     this->CopyData(typeEnumeration, (Ptr)&enumeration, sizeof(enumeration));
  371.     } // TDescriptor::MakeEnumeration 
  372.  
  373. //----------------------------------------------------------------------------------------
  374. // TDescriptor::MakeDescType: 
  375. //----------------------------------------------------------------------------------------
  376. void TDescriptor::MakeDescType(const DescType data)
  377.     {
  378.     this->CopyData(typeType, (Ptr)&data, sizeof(DescType));
  379.     } // TDescriptor::MakeDescType 
  380.  
  381. //----------------------------------------------------------------------------------------
  382. // TDescriptor::MakeKeyword: 
  383. //----------------------------------------------------------------------------------------
  384. void TDescriptor::MakeKeyword(const AEKeyword theKeyword)
  385.     {
  386.     this->CopyData(typeKeyword, (Ptr)&theKeyword, sizeof(AEKeyword));
  387.     } // TDescriptor::MakeKeyword 
  388.  
  389. //----------------------------------------------------------------------------------------
  390. // TDescriptor::MakeOrdinal: 
  391. //----------------------------------------------------------------------------------------
  392. void TDescriptor::MakeOrdinal(const DescType data)
  393.     {
  394.     this->CopyData(typeAbsoluteOrdinal, (Ptr)&data, sizeof(DescType));
  395.     } // TDescriptor::MakeOrdinal 
  396.     
  397. //----------------------------------------------------------------------------------------
  398. // TDescriptor::MakeTypeOrInteger:
  399. //
  400. // This is useful for debugging; it makes a 'type' if the data
  401. // appears to consist of printable characters (e.g. 'ABCD'), but
  402. // otherwise it makes an integer (e.g. -12).
  403. //----------------------------------------------------------------------------------------
  404. void TDescriptor::MakeTypeOrInteger(const DescType data)
  405.     {
  406.     if(((data >= 'A000') && (data <= 'Zzzz')) || ((data >= 'a000') && (data <= 'zzzz')))
  407.         this->MakeDescType(data);
  408.     else
  409.         this->MakeLong(data);
  410.     } // TDescriptor::MakeTypeOrInteger 
  411.  
  412. //----------------------------------------------------------------------------------------
  413. // TDescriptor::MakePoint: 
  414. //----------------------------------------------------------------------------------------
  415. void TDescriptor::MakePoint(const Point& thePoint)
  416.     {
  417.     this->CopyData(typeQDPoint, (Ptr)&thePoint, sizeof(Point));
  418.     } // TDescriptor::MakePoint 
  419.  
  420. //----------------------------------------------------------------------------------------
  421. // TDescriptor::MakePoint: 
  422. //----------------------------------------------------------------------------------------
  423. void TDescriptor::MakePoint(const short h, const short v)
  424.     {
  425.     Point thePoint;
  426.     
  427.     thePoint.v = v;
  428.     thePoint.h = h;
  429.     this->MakePoint(thePoint);
  430.     } // TDescriptor::MakePoint 
  431.  
  432. //----------------------------------------------------------------------------------------
  433. // TDescriptor::MakeRect: 
  434. //----------------------------------------------------------------------------------------
  435. void TDescriptor::MakeRect(const Rect& theRect)
  436.     {
  437.     this->CopyData(typeQDRectangle, (Ptr)&theRect, sizeof(Rect));
  438.     } // TDescriptor::MakeRect 
  439.  
  440. //----------------------------------------------------------------------------------------
  441. // TDescriptor::MakeString: 
  442. //----------------------------------------------------------------------------------------
  443. void TDescriptor::MakeString(Str255 data)
  444.     {
  445.     Size length = data[0];
  446.     
  447.     this->CopyData(typeChar, (Ptr)&data[1], length);
  448.     } // TDescriptor::MakeString 
  449.  
  450. //----------------------------------------------------------------------------------------
  451. // TDescriptor::MakeDateTimeRec: 
  452. //----------------------------------------------------------------------------------------
  453. void TDescriptor::MakeDateTimeRec(const DateTimeRec dateTime)
  454.     {
  455.     this->CopyData(typeDateTimeRec, (Ptr)&dateTime, sizeof(DateTimeRec));
  456.     } // TDescriptor::MakeDateTimeRec 
  457.  
  458. //----------------------------------------------------------------------------------------
  459. // TDescriptor::MakeDateTimeRec: 
  460. //----------------------------------------------------------------------------------------
  461. void TDescriptor::MakeDateTimeRec(const long secsSince1904)
  462.     {
  463.     DateTimeRec dateTime;
  464.     
  465.     //
  466.     // Let the OSUtilities do the hard work of converting seconds
  467.     // since 1904 into a DateTimeRec
  468.     //
  469.     SecondsToDate(secsSince1904,&dateTime);
  470.     this->MakeDateTimeRec(dateTime);
  471.     } // TDescriptor::MakeDateTimeRec 
  472.  
  473. //----------------------------------------------------------------------------------------
  474. // TDescriptor::MakeLongDateTimeRec: 
  475. //----------------------------------------------------------------------------------------
  476. void TDescriptor::MakeLongDateTimeRec(const LongDateRec dateTime)
  477.     {
  478.     this->CopyData(typeLongDateTimeRec, (Ptr)&dateTime, sizeof(LongDateRec));
  479.     } // TDescriptor::MakeLongDateTimeRec 
  480.  
  481. //----------------------------------------------------------------------------------------
  482. // TDescriptor::MakeLongDateTimeRec: 
  483. //----------------------------------------------------------------------------------------
  484. void TDescriptor::MakeLongDateTimeRec(const DateTimeRec dateTime)
  485.     {
  486.     LongDateRec longDateTime;
  487.         
  488.     longDateTime.od.eraAlt = 0;
  489.     longDateTime.od.oldDate = dateTime;
  490.     
  491.     this->MakeLongDateTimeRec(longDateTime);
  492.     } // TDescriptor::MakeLongDateTimeRec 
  493.  
  494. //----------------------------------------------------------------------------------------
  495. // TDescriptor::MakeLongDateTimeRec: 
  496. //----------------------------------------------------------------------------------------
  497. void TDescriptor::MakeLongDateTimeRec(LongDateTime lsecs)
  498.     {
  499.     LongDateRec longDateTime;
  500.     
  501.     LongSecondsToDate(&lsecs, &longDateTime);
  502.     this->MakeLongDateTimeRec(longDateTime);
  503.     } // TDescriptor::MakeLongDateTimeRec 
  504.  
  505. //----------------------------------------------------------------------------------------
  506. // TDescriptor::MakeLongDateTime: 
  507. //----------------------------------------------------------------------------------------
  508. void TDescriptor::MakeLongDateTime(const LongDateTime lsecs)
  509.     {
  510.     this->CopyData(typeLongDateTime, (Ptr)&lsecs, sizeof(LongDateTime));
  511.     } // TDescriptor::MakeLongDateTime 
  512.  
  513. //----------------------------------------------------------------------------------------
  514. // TDescriptor::MakeFSS: 
  515. //----------------------------------------------------------------------------------------
  516. void TDescriptor::MakeFSS(const FSSpec& spec)
  517.     {
  518.     this->CopyData(typeFSS, (Ptr)&spec, sizeof(FSSpec));
  519.     } // TDescriptor::MakeFSS 
  520.  
  521. //----------------------------------------------------------------------------------------
  522. // TDescriptor::AdoptAlias: 
  523. //
  524. // Takes the provided alias handle and keeps it forever.
  525. //----------------------------------------------------------------------------------------
  526. void TDescriptor::AdoptAlias(Handle alias)
  527.     {
  528.     this->AdoptHandle(typeAlias, alias);
  529.     } // TDescriptor::AdoptAlias 
  530.     
  531. //----------------------------------------------------------------------------------------
  532. // TDescriptor::MakeAlias: 
  533. //
  534. // You would think that someone would have spent five minutes to make a coercion
  535. // handler that goes from FSSpecs to Alias records, but nooooooo...
  536. //----------------------------------------------------------------------------------------
  537. void TDescriptor::MakeAlias(FSSpec& spec)
  538.     {
  539.     AliasHandle alias;
  540.     
  541.     FailErr(NewAliasMinimal(&spec, &alias));
  542.     this->AdoptAlias((Handle)alias);
  543.     } // TDescriptor::MakeAlias 
  544.  
  545. //----------------------------------------------------------------------------------------
  546. // TDescriptor::MakeProcessSerialNumber: 
  547. //----------------------------------------------------------------------------------------
  548. void TDescriptor::MakeProcessSerialNumber(ProcessSerialNumber psn)
  549.     {
  550.     this->CopyData(typeProcessSerialNumber, (Ptr)&psn, sizeof(ProcessSerialNumber));
  551.     } // TDescriptor::MakeProcessSerialNumber 
  552.  
  553. //----------------------------------------------------------------------------------------
  554. // TDescriptor::MakeObjectSpecifier: 
  555. //----------------------------------------------------------------------------------------
  556. void TDescriptor::MakeObjectSpecifier(DescType desiredClass, TDescriptor container, DescType keyForm, TDescriptor keyData, Boolean disposeInputs)
  557.     {
  558.     FailErr(CreateObjSpecifier(desiredClass,container,keyForm,keyData,disposeInputs,*this));
  559.     } // TDescriptor::MakeObjectSpecifier 
  560.  
  561. //----------------------------------------------------------------------------------------
  562. // TDescriptor::MakeCompDescriptor: 
  563. //----------------------------------------------------------------------------------------
  564. void TDescriptor::MakeCompDescriptor(DescType comparisonOperator, DescType propertyIdentifier, TDescriptor compareWith, Boolean disposeInputs)
  565.     {
  566.     TDescriptor operand1;
  567.     TDescriptor propertyIDDesc;
  568.     TDescriptor objectBeingExamined;
  569.     
  570.     //
  571.     // 'objectBeingExamined' is a special object specifier that only
  572.     // has meaning in the context of a comparison descriptor
  573.     //
  574.     objectBeingExamined.AdoptHandle(typeObjectBeingExamined,nil);
  575.     
  576.     //
  577.     // Operand1 is "fPropertyIdentifier of (object being examined)"
  578.     //
  579.     propertyIDDesc.MakeDescType(propertyIdentifier);
  580.     operand1.MakeObjectSpecifier(cProperty, objectBeingExamined, formPropertyID, propertyIDDesc, true);
  581.  
  582.     //
  583.     // Make a compDescriptor of operand1 compared with (fComparisonOperator) fCompareWith
  584.     //
  585.     CreateCompDescriptor(comparisonOperator, operand1, compareWith, disposeInputs, *this);
  586.     } // TDescriptor::MakeCompDescriptor 
  587.  
  588. //----------------------------------------------------------------------------------------
  589. // TDescriptor::GetBlock: 
  590. //----------------------------------------------------------------------------------------
  591. void TDescriptor::GetBlock(Ptr data, Size length, DescType desiredType) const
  592.     {
  593.     if(this->DataHandleIsNil())
  594.         FailErr(errAECantSupplyType);
  595.     
  596.     if(this->DescriptorType() != desiredType)
  597.         {
  598.         TDescriptor coerceData;
  599.         
  600.         coerceData = this->Coerce(desiredType);
  601.         coerceData.GetBlock(data,length,desiredType);
  602.         coerceData.Dispose();
  603.         }
  604.     else
  605.         {
  606.         //
  607.         // It would be just wrong to have a situation where a
  608.         // descriptor is of the requested type, but not of the
  609.         // requested length.  This method is only usable for
  610.         // fixed-size blocks
  611.         //
  612.         if(GetHandleSize(fDataHandle) != length)
  613.             {
  614.             FailErr(errAECorruptData);
  615.             }
  616.  
  617.         BlockMove(*fDataHandle, data, length);
  618.         }
  619.     } // TDescriptor::GetBlock 
  620.  
  621. //----------------------------------------------------------------------------------------
  622. // TDescriptor::GetLong: 
  623. //----------------------------------------------------------------------------------------
  624. long TDescriptor::GetLong() const
  625.     {
  626.     long result = 0;
  627.  
  628.     this->GetBlock((Ptr)&result, sizeof(long), typeLongInteger);
  629.  
  630.     return result;
  631.     } // TDescriptor::GetLong 
  632.     
  633. //----------------------------------------------------------------------------------------
  634. // TDescriptor::GetBoolean: 
  635. //----------------------------------------------------------------------------------------
  636. Boolean TDescriptor::GetBoolean() const
  637.     {
  638.     Boolean result = 0;
  639.  
  640.     this->GetBlock((Ptr)&result, sizeof(Boolean), typeBoolean);
  641.  
  642.     return result;
  643.     } // TDescriptor::GetBoolean 
  644.  
  645. //----------------------------------------------------------------------------------------
  646. // TDescriptor::GetDescType: 
  647. //----------------------------------------------------------------------------------------
  648. DescType TDescriptor::GetDescType() const
  649.     {
  650.     DescType result = 0;
  651.     
  652.     this->GetBlock((Ptr)&result, sizeof(DescType), typeType);
  653.     
  654.     return result;
  655.     } // TDescriptor::GetDescType 
  656.  
  657. //----------------------------------------------------------------------------------------
  658. // TDescriptor::GetKeyword: 
  659. //----------------------------------------------------------------------------------------
  660. AEKeyword TDescriptor::GetKeyword() const
  661.     {
  662.     AEKeyword result = 0;
  663.     
  664.     this->GetBlock((Ptr)&result, sizeof(AEKeyword), typeKeyword);
  665.     
  666.     return result;
  667.     } // TDescriptor::GetKeyword 
  668.     
  669. //----------------------------------------------------------------------------------------
  670. // TDescriptor::GetEnumeration: 
  671. //----------------------------------------------------------------------------------------
  672. DescType TDescriptor::GetEnumeration() const
  673.     {
  674.     DescType result = 0;
  675.     
  676.     this->GetBlock((Ptr)&result, sizeof(DescType), typeEnumeration);
  677.     
  678.     return result;
  679.     } // TDescriptor::GetEnumeration 
  680.  
  681. //----------------------------------------------------------------------------------------
  682. // TDescriptor::GetOrdinal: 
  683. //----------------------------------------------------------------------------------------
  684. DescType TDescriptor::GetOrdinal() const
  685.     {
  686.     DescType result = 0;
  687.     
  688.     this->GetBlock((Ptr)&result, sizeof(DescType), typeAbsoluteOrdinal);
  689.     
  690.     return result;
  691.     } // TDescriptor::GetOrdinal 
  692.  
  693. //----------------------------------------------------------------------------------------
  694. // TDescriptor::GetPoint: 
  695. //----------------------------------------------------------------------------------------
  696. Point TDescriptor::GetPoint() const
  697.     {
  698.     Point result;
  699.  
  700.     this->GetBlock((Ptr)&result, sizeof(Point), typeQDPoint);
  701.  
  702.     return result;
  703.     } // TDescriptor::GetPoint 
  704.  
  705. //----------------------------------------------------------------------------------------
  706. // TDescriptor::GetRect: 
  707. //----------------------------------------------------------------------------------------
  708. Rect TDescriptor::GetRect() const
  709.     {
  710.     Rect result;
  711.  
  712.     this->GetBlock((Ptr)&result, sizeof(Rect), typeQDRectangle);
  713.     
  714.     return result;
  715.     } // TDescriptor::GetRect 
  716.  
  717. //----------------------------------------------------------------------------------------
  718. // TDescriptor::GetString: 
  719. //----------------------------------------------------------------------------------------
  720. void TDescriptor::GetString(Str255 result) const
  721.     {
  722.     result[0] = 0;
  723.  
  724.     if(this->DataHandleIsNil())
  725.         FailErr(errAECantSupplyType);
  726.         
  727.     if(this->DescriptorType() == typeChar)
  728.         {
  729.         Size length = GetHandleSize(fDataHandle);
  730.         if(length > 255)
  731.             length = 255;
  732.         BlockMove(*fDataHandle, (Ptr)&result[1], length);
  733.         result[0] = (unsigned char) length;
  734.         }
  735.     else
  736.         {
  737.         TDescriptor makeDataString;
  738.         
  739.         makeDataString = this->Coerce(typeChar);
  740.         //ASSERT(makeDataString.DescriptorType() == typeChar);
  741.         makeDataString.GetString(result);
  742.         makeDataString.Dispose();
  743.         }
  744.     } // TDescriptor::GetString 
  745.  
  746. //----------------------------------------------------------------------------------------
  747. // TDescriptor::GetDateTimeRec: 
  748. //----------------------------------------------------------------------------------------
  749. DateTimeRec TDescriptor::GetDateTimeRec() const
  750.     {
  751.     DateTimeRec dateTime;
  752.     
  753.     //
  754.     // We'll do our own coercion from typeLongInteger, if necessary.
  755.     // We should really have a coercion handler for this
  756.     //
  757.     if(this->DescriptorType() == typeLongInteger)
  758.         {
  759.         long secsSince1904 = this->GetLong();
  760.         SecondsToDate(secsSince1904,&dateTime);
  761.         }
  762.     else
  763.         {
  764.         //
  765.         // Get the time date rec
  766.         //
  767.         this->GetBlock( (Ptr)&dateTime, sizeof(DateTimeRec), typeDateTimeRec);
  768.         }
  769.     
  770.     return dateTime;
  771.     } // TDescriptor::GetDateTimeRec 
  772.  
  773. //----------------------------------------------------------------------------------------
  774. // TDescriptor::GetFSS: 
  775. //----------------------------------------------------------------------------------------
  776. void TDescriptor::GetFSS(FSSpec& spec) const
  777.     {
  778.     this->GetBlock((Ptr)&spec, sizeof(FSSpec), typeFSS);
  779.     } // TDescriptor::GetFSS 
  780.  
  781. //----------------------------------------------------------------------------------------
  782. // InterpretCompareResult:
  783. //
  784. // Given two keys and a comparison opperator, this function determines if
  785. // the comparison between key2 and key1 is true or false.  key1 and key2 should
  786. // be either two long integers representing the various values of the two descriptors
  787. // being compared, or key1 may be set to 0 and key2 set to -1 (key2 < key1), 0
  788. // (key1 == key2) or 1 (key2 > key1).
  789. //
  790. // This function is used by GeneralCompare, which is used by TDescriptor::Compare
  791. //----------------------------------------------------------------------------------------
  792. Boolean InterpretCompareResult(DescType comparisonOperator, long key1, long key2 )
  793.     {
  794.     switch(comparisonOperator)
  795.         {
  796.         case kAEEquals:
  797.             {
  798.             return key1 == key2;
  799.             }
  800.         
  801.         case kASNotEqual:
  802.             {
  803.             return key1 != key2;
  804.             }
  805.         
  806.         case kAEGreaterThan:
  807.             {
  808.             return key1 > key2;
  809.             }
  810.         
  811.         case kAEGreaterThanEquals:
  812.             {
  813.             return key1 >= key2;
  814.             }
  815.         
  816.         case kAELessThan:
  817.             {
  818.             return key1 < key2;
  819.             }
  820.         
  821.         case kAELessThanEquals:
  822.             {
  823.             return key1 <= key2;
  824.             }
  825.         
  826.         //
  827.         // ••• Perhaps we should fail if we don't recognize the comparisonOperator
  828.         //
  829.         default:
  830.             {
  831.             return false;
  832.             }
  833.         }
  834.     } // InterpretCompareResult 
  835.  
  836. //----------------------------------------------------------------------------------------
  837. // GeneralCompare: 
  838. //
  839. // This is a general comparison routine that works on streams of bytes.  It is assumed
  840. // that the data being compared follows the same ordering rules as strings.  The
  841. // 'caseSensitive' flag should always be true for non-string objects, of course.
  842. //----------------------------------------------------------------------------------------
  843. Boolean GeneralCompare(DescType comparisonOperator, Ptr data, Size length, Ptr compareWith, Size comparisonLength, Boolean caseSensitive)
  844.     {
  845.     Boolean comparisonResult = false;
  846.     long i = 0;
  847.         
  848.     switch(comparisonOperator)
  849.         {
  850.         case kAEEquals:        
  851.         case kASNotEqual:
  852.         case kAEGreaterThan:
  853.         case kAEGreaterThanEquals:
  854.         case kAELessThan:
  855.         case kASLessThanOrEqual:
  856.             {
  857.             short intermediateResult = 0;
  858.             Size max = (length < comparisonLength ? length : comparisonLength);
  859.             
  860.             //
  861.             // We have a little bit of code duplication here
  862.             // to make the code run a little faster
  863.             //
  864.             if(caseSensitive)
  865.                 {
  866.                 for(i=0; i < max; ++i)
  867.                     {
  868.                     if(*((unsigned char*)compareWith) > *((unsigned char*)data))
  869.                         {
  870.                         intermediateResult = 1;
  871.                         break;
  872.                         }
  873.                     else if(*((unsigned char*)compareWith) < *((unsigned char*)data))
  874.                         {
  875.                         intermediateResult = -1;
  876.                         break;
  877.                         }
  878.                     ++compareWith;
  879.                     ++data;
  880.                     }
  881.                 }
  882.             else
  883.                 {
  884.                 for(i=0; i < max; ++i)
  885.                     {
  886.                     unsigned char compareWithChar = *((unsigned char*)compareWith);
  887.                     unsigned char dataChar = *((unsigned char*)data);
  888.                     
  889.                     if((compareWithChar >= 'a') && (compareWithChar <= 'z'))
  890.                         compareWithChar = compareWithChar - 'a' + 'A';
  891.                     if((dataChar >= 'a') && (dataChar <= 'z'))
  892.                         dataChar = dataChar - 'a' + 'A';
  893.                         
  894.                     if(compareWithChar > dataChar)
  895.                         {
  896.                         intermediateResult = 1;
  897.                         break;
  898.                         }
  899.                     else if(compareWithChar < dataChar)
  900.                         {
  901.                         intermediateResult = -1;
  902.                         break;
  903.                         }
  904.                     ++compareWith;
  905.                     ++data;
  906.                     }
  907.                 }
  908.             
  909.             if(intermediateResult == 0)
  910.                 intermediateResult = (comparisonLength > length) - (comparisonLength < length);
  911.             
  912.             comparisonResult = InterpretCompareResult(comparisonOperator,0,intermediateResult);
  913.             
  914.             break;
  915.             }
  916.         
  917.         case kAEBeginsWith:
  918.             {
  919.             comparisonResult = GeneralCompare(kAEEquals, data, comparisonLength, compareWith, comparisonLength,caseSensitive);
  920.             break;
  921.             }
  922.             
  923.         case kAEEndsWith:
  924.             {
  925.             i = (length - comparisonLength);
  926.             if(i >= 0)
  927.                 comparisonResult = GeneralCompare(kAEEquals, data + i, comparisonLength, compareWith, comparisonLength,caseSensitive);
  928.             break;
  929.             }
  930.             
  931.         case kAEContains:
  932.             {
  933.             for(i=0;i<=length - comparisonLength;++i)
  934.                 {
  935.                 if(GeneralCompare(kAEEquals, data + i, comparisonLength, compareWith, comparisonLength,caseSensitive))
  936.                     {
  937.                     comparisonResult = true;
  938.                     break;
  939.                     }
  940.                 }
  941.             
  942.             break;
  943.             }
  944.             
  945.         default:
  946.             {
  947.             comparisonResult = false;
  948.             }
  949.         }
  950.     
  951.     return comparisonResult;
  952.     } // GeneralCompare 
  953.  
  954. //----------------------------------------------------------------------------------------
  955. // TDescriptor::Compare: 
  956. //----------------------------------------------------------------------------------------
  957. Boolean TDescriptor::Compare(DescType comparisonOperator, Str255 withString) const
  958.     {
  959.     Str255 thisString;
  960.     Size thisSize;
  961.     Size withSize;
  962.     Boolean compareResult = false;
  963.     
  964.     //
  965.     // Fetch a copy of 'thisString' (which we will freely destroy later)
  966.     //
  967.     this->GetString(thisString);
  968.     thisSize = (unsigned char)thisString[0];
  969.     withSize = (unsigned char)withString[0];
  970.  
  971.     switch(comparisonOperator)
  972.         {
  973.         //
  974.         // Check to see if we can find the string anywhere inside
  975.         //
  976.         case kAEContains:
  977.             {
  978.             long    i;
  979.             
  980.             unsigned char* a = &thisString[0];
  981.             for(i=0;i<thisSize - withSize + 1;++i)
  982.                 {
  983.                 *a = (unsigned char)withSize;
  984.                 compareResult = (IUEqualString(a, withString) == 0);
  985.                 if(compareResult == true)
  986.                     break;
  987.                 ++a;
  988.                 }
  989.             }
  990.             break;
  991.         
  992.         //
  993.         // Relational tests are easy:  use IUCompString
  994.         //
  995.         case kAEGreaterThan:
  996.         case kAEGreaterThanEquals:
  997.         case kAELessThan:
  998.         case kASLessThanOrEqual:
  999.             {
  1000.             compareResult = InterpretCompareResult(comparisonOperator, IUCompString(thisString, withString), 0);
  1001.             }
  1002.             break;
  1003.         
  1004.         //
  1005.         // For AEEndsWith, move the end of the string down to
  1006.         // the beginning of the string, then fall through to
  1007.         // the 'begins with' case
  1008.         //
  1009.         // International allert:  this could clip a two-byte
  1010.         // character in half, but doing so probably won't cause
  1011.         // a problem, since we are looking for exact matches.
  1012.         //
  1013.         case kAEEndsWith:
  1014.             {
  1015.             if(withSize <= thisSize)
  1016.                 BlockMove((Ptr)&thisString[thisSize - withSize + 1],(Ptr)&thisString[1],withSize);
  1017.             }
  1018.             // !!! fall through
  1019.             
  1020.         //
  1021.         // For kAEBeginsWith, set the length of the 'thisString'
  1022.         // to the length of the 'withString' and do an equality test
  1023.         //
  1024.         // International allert:  this could clip a two-byte
  1025.         // character in half, but doing so probably won't cause
  1026.         // a problem, since we are looking for exact matches.
  1027.         //
  1028.         case kAEBeginsWith:
  1029.             {
  1030.             thisString[0] = (unsigned char)withSize;
  1031.             }
  1032.             // !!! fall through...
  1033.         
  1034.         //
  1035.         // kAEEquals and kASNotEqual must come immediately after
  1036.         // begins with and ends with
  1037.         //
  1038.         case kAEEquals:
  1039.         case kASNotEqual:
  1040.             {
  1041.             compareResult = (IUEqualString(thisString, withString) == 0);
  1042.             if(comparisonOperator == kASNotEqual)
  1043.                 compareResult = !compareResult;
  1044.             }
  1045.             break;
  1046.         
  1047.         //
  1048.         // Shouldn't ever get here...
  1049.         //
  1050.         default:
  1051.             {
  1052.             compareResult = GeneralCompare(comparisonOperator,(Ptr)&thisString[1],thisSize,(Ptr)&withString[1],withSize,false);
  1053.             }
  1054.             break;
  1055.         }
  1056.     
  1057.     return compareResult;
  1058.     } // TDescriptor::Compare 
  1059.  
  1060. //----------------------------------------------------------------------------------------
  1061. // TDescriptor::Compare: 
  1062. //
  1063. // Compare two descriptors.  ComparisonOperator should be one of the following:
  1064. //
  1065. // kAEEquals, kASNotEqual, kAEGreaterThan, kAEGreaterThanEquals, kAELessThan,
  1066. // kASLessThanOrEqual, kAEBeginsWith, kAEEndsWith, or kAEContains
  1067. //----------------------------------------------------------------------------------------
  1068. Boolean TDescriptor::Compare(DescType comparisonOperator, TDescriptor& compareWith) const
  1069.     {
  1070.     Boolean compareResult = false;
  1071.     
  1072.     //
  1073.     // It might be nice to try to do a type coercion here, but for now
  1074.     // we only compare descriptors of the same type
  1075.     //
  1076.     if(this->DescriptorType() != compareWith.DescriptorType())
  1077.         FailErr(errAEEventNotHandled);
  1078.     
  1079.     switch(this->DescriptorType())
  1080.         {
  1081.         case typeChar:
  1082.             {
  1083.             Str255 withString;
  1084.  
  1085.             compareWith.GetString(withString);
  1086.             compareResult = this->Compare(comparisonOperator, withString);
  1087.  
  1088.             break;
  1089.             }
  1090.             break;
  1091.         
  1092.         //
  1093.         // We convert DateTimeRecs into integers for comparison so that
  1094.         // someone can supply "the 300th day of January", and it will compare
  1095.         // as being larger than "the 2nd day of February".
  1096.         //
  1097.         // Begins with, ends with and contains are meaningless for dates, though.
  1098.         //
  1099.         case typeLongInteger:
  1100.         case typeDateTimeRec:
  1101.             {            
  1102.             compareResult = InterpretCompareResult(comparisonOperator, this->GetLong(), compareWith.GetLong() );
  1103.             }
  1104.             break;
  1105.         
  1106.         //
  1107.         // If we don't know what type this is, we'll do our best
  1108.         // to do a generic comparison.  This can result in some
  1109.         // very stupid comparisons, but that's life.
  1110.         //
  1111.         default:
  1112.             {
  1113.             Handle        withHandle = compareWith.DataHandle();
  1114.             short        thisState;
  1115.             short        withState;
  1116.             Size        thisSize;
  1117.             Size        withSize;
  1118.             
  1119.             thisState = HGetState(fDataHandle);
  1120.             withState = HGetState(withHandle);
  1121.             thisSize = GetHandleSize(fDataHandle);
  1122.             withSize = GetHandleSize(withHandle);
  1123.             
  1124.             compareResult = GeneralCompare(comparisonOperator,(Ptr)*fDataHandle,thisSize,(Ptr)*withHandle,withSize,true);
  1125.             
  1126.             HSetState(fDataHandle,thisState);
  1127.             HSetState(withHandle,withState);
  1128.             }
  1129.             break;
  1130.         }
  1131.         
  1132.     return compareResult;
  1133.     } // TDescriptor::Compare
  1134.  
  1135. //========================================================================================
  1136. // CLASS TDescriptorLoop
  1137. //
  1138. // The class TDescriptorLoop is used by the macro FOREACHDESCRIPTOR.  Note that the
  1139. // descriptor returned by "Next" is a copy that must be disposed of by the programmer.
  1140. //
  1141. // We could have TDescriptorLoop keep track of the descriptor it created, and have it
  1142. // dispose it when done.  This would necessitate an 'orphan' method, though, in case
  1143. // someone else wanted to adopt the descriptor.
  1144. //========================================================================================
  1145.  
  1146. //----------------------------------------------------------------------------------------
  1147. // TDescriptorLoop::Next: 
  1148. //
  1149. // If 'key' is not nil, it is filled in with the keyword from the i'th item of the
  1150. // list (if the list is a record)
  1151. //
  1152. // If 'dataHandle' is not nil, it is filled in with the data handle from the i'th
  1153. // item of the list.  This is only done to be nice to the FOREACHTOKEN macro.
  1154. //----------------------------------------------------------------------------------------
  1155. Boolean TDescriptorLoop::Next(TDescriptor& d, AEKeyword* key, Handle* dataHandle)
  1156.     {
  1157.     Boolean moreToDo = false;
  1158.     
  1159.     //
  1160.     // Set up on the first time through the loop
  1161.     //
  1162.     if(fIndex == 0)
  1163.         {
  1164.         fCount = fDescriptorList->CountItems();
  1165.         if(d.IsNullDescriptor() == false)
  1166.             {
  1167.             DebugStr("\pTDescriptorLoop::Next:  'd' was not null on first iteration!");
  1168.             FailErr(errAEEventFailed);
  1169.             }
  1170.         }
  1171.  
  1172.     //
  1173.     // Advance to the next item in the list...
  1174.     //
  1175.     fIndex++;
  1176.     
  1177.     //
  1178.     // Dispose of the 'd' from last time through the loop
  1179.     //
  1180.     d.Dispose();
  1181.     
  1182.     //
  1183.     // Are there still items in the list?
  1184.     //
  1185.     if (fIndex <= fCount)
  1186.         {
  1187.         //
  1188.         // At this point, we could check to see if 'fDescriptorList' actually
  1189.         // points to something that is _not_ a list; if so, we coule return a
  1190.         // _reference_ to the single object, and set a field that indicates that
  1191.         // 'd' is a reference, and should not be disposed next time through the
  1192.         // loop.  The reason we do not do this is that 'd' will be disposed by
  1193.         // the client code if there is a failure, and there is no good way for
  1194.         // the client to know if d is a reference or not.  We could remember
  1195.         // what 'd' was and clean it up in our destructor, but failures can
  1196.         // cause our TDescriptorLoop object to be orphaned without ever being
  1197.         // destructed.
  1198.         //
  1199.         d = fDescriptorList->GetNthDescriptor(fIndex, typeWildCard, key);
  1200.         
  1201.         moreToDo = true;
  1202.         }
  1203.     //
  1204.     // No more items, clean up
  1205.     //
  1206.     else
  1207.         {
  1208.         if(key != nil)
  1209.             *key = typeNull;
  1210.         d.MakeNull();
  1211.         }
  1212.     
  1213.     //
  1214.     // Fill in the 'dataHandle' parameter if it was passed in.
  1215.     // (We only do this to make life easy for the FOREACHTOKEN macro)
  1216.     //
  1217.     if(dataHandle != nil)
  1218.         *dataHandle = d.DataHandle();
  1219.     
  1220.     return moreToDo;
  1221.     } // TDescriptorLoop::Next 
  1222.  
  1223.  
  1224. //----------------------------------------------------------------------------------------
  1225. // TDescriptor::MakeEmptyList:
  1226. //
  1227. // Make an empty descriptor list.  It is usually not necessary to make an empty list,
  1228. // because all of the TDescriptor routines will interpret null descriptors as
  1229. // empty lists.  Sometimes it is necessary to return an empty list as the result of
  1230. // an AppleEvent handler, though, and in this case a null descriptor is _not_ equivalent.
  1231. //
  1232. // By default, include no factored data and make an AEList.
  1233. //----------------------------------------------------------------------------------------
  1234. void TDescriptor::MakeEmptyList()
  1235.     {
  1236.     this->CreateList(kMakeAEList);
  1237.     } // TDescriptor::MakeEmptyList 
  1238.  
  1239. //----------------------------------------------------------------------------------------
  1240. // TDescriptor::MakeList: 
  1241. //
  1242. // If this descriptor is null, an empty list is created.  If this descriptor is not
  1243. // empty, then a list is created and this descriptor is placed inside it.  If this
  1244. // descriptor is already a list, then no action is taken.
  1245. //
  1246. // ••• DANGER:  Does a coerce-in-place!
  1247. //----------------------------------------------------------------------------------------
  1248. void TDescriptor::MakeList()
  1249.     {
  1250.     if(this->IsNullDescriptor())
  1251.         {
  1252.         this->CreateList();
  1253.         }
  1254.     else if(this->DescriptorType() != typeAEList)
  1255.         {
  1256.         this->CoerceInPlace(typeAEList);
  1257.         }
  1258.     } // TDescriptor::MakeList 
  1259.     
  1260. //----------------------------------------------------------------------------------------
  1261. // TDescriptor::CountItems:
  1262. //
  1263. // Count the items in a descriptor list. If this descriptor is not of typeAEList, then it
  1264. // only has one item, and if the descriptor is null, then it has no items.
  1265. //----------------------------------------------------------------------------------------
  1266. long TDescriptor::CountItems() const
  1267.     {
  1268.     long items = 1;
  1269.     if(this->IsNullDescriptor())
  1270.         items = 0;
  1271.     else if((this->DescriptorType() == typeAEList) || (this->DescriptorType() == typeAERecord))
  1272.         FailErr(AECountItems(*this, &items));
  1273.     return items;
  1274.     } // TDescriptor::CountItems 
  1275.  
  1276. //----------------------------------------------------------------------------------------
  1277. // TDescriptor::GetNthDescriptor:
  1278. //
  1279. // Get the indexed descriptor from an event.  This method will fail if given an index
  1280. // less than one or greater than the count returned by TDescriptor::CountItems.
  1281. // The descriptor returned is _always_ a copy that must be disposed of with
  1282. // TDescriptor::Dispose.
  1283. //----------------------------------------------------------------------------------------
  1284. TDescriptor TDescriptor::GetNthDescriptor(long index, DescType desiredType, AEKeyword* key) const
  1285.     {
  1286.     TDescriptor descriptor;
  1287.     AEKeyword ignoreKey;
  1288.     
  1289.     if(key == nil)
  1290.         key = &ignoreKey;
  1291.         
  1292.     //
  1293.     // We can "GetNthDescriptor" on an item that is not of typeAEList
  1294.     // if the index is one; we do this by cloning ourself
  1295.     // (n.b. AERecords are also lists)
  1296.     //
  1297.     if((DescriptorType() != typeAEList) && (DescriptorType() != typeAERecord))
  1298.         {
  1299.         if(index != 1)
  1300.             FailErr(-1);        // ••• index out of range
  1301.         
  1302.         *key = typeWildCard; 
  1303.         descriptor = this->Clone();
  1304.         }
  1305.     else
  1306.         {
  1307.         FailErr(AEGetNthDesc(*this, index, desiredType, key, descriptor));
  1308.         }
  1309.     
  1310.     return descriptor;
  1311.     } // TDescriptor::GetNthDescriptor 
  1312.  
  1313. //----------------------------------------------------------------------------------------
  1314. // TDescriptor::AddDescriptor:
  1315. //
  1316. // Add data to a descriptor list at a specified index, replacing any item already stored
  1317. // at that position.
  1318. //----------------------------------------------------------------------------------------
  1319. void TDescriptor::AddDescriptor(long index, TDescriptor& data)
  1320.     {
  1321.     //
  1322.     // If the list is completely empty, just put the data directly into
  1323.     // this descriptor (don't make a list)
  1324.     //
  1325.     if(this->IsNullDescriptor())
  1326.         {
  1327.         this->CopyDesc(data);
  1328.         }
  1329.     else
  1330.         {
  1331.         // If we're not a list yet, we'd better make ourselves one now.
  1332.         if(this->DescriptorType() != typeAEList)
  1333.             this->MakeList();
  1334.         FailErr(AEPutDesc(*this, index, data));
  1335.         }
  1336.     } // TDescriptor::AddDescriptor 
  1337.  
  1338. //----------------------------------------------------------------------------------------
  1339. // TDescriptor::AddDescriptor:
  1340. //
  1341. // Add data to a descriptor list at the end of the list
  1342. //----------------------------------------------------------------------------------------
  1343. void TDescriptor::AddDescriptor(TDescriptor& data)
  1344.     {
  1345.     this->AddDescriptor(0,data);
  1346.     } // TDescriptor::AddDescriptor 
  1347.  
  1348. //----------------------------------------------------------------------------------------
  1349. // TDescriptor::AddData: 
  1350. //----------------------------------------------------------------------------------------
  1351. void TDescriptor::AddData(long index, DescType descType, Ptr data, Size length)
  1352.     {
  1353.     //
  1354.     // If the list is completely empty, we'd better make an empty list
  1355.     // (the type coercion from null to typeAEList probably works,
  1356.     // but I have not tested it yet; the following two lines may
  1357.     // be superfluous)
  1358.     //
  1359.     if(this->IsNullDescriptor())
  1360.         this->MakeEmptyList();
  1361.     
  1362.     //
  1363.     // If we're not a list yet, we'd better make ourselves one now.
  1364.     //
  1365.     if(this->DescriptorType() != typeAEList)
  1366.         this->CoerceInPlace(typeAEList);
  1367.     
  1368.     //
  1369.     // Put the data into the list
  1370.     //
  1371.     FailErr(AEPutPtr(*this,index,descType,data,length));
  1372.     } // TDescriptor::AddData 
  1373.  
  1374. //----------------------------------------------------------------------------------------
  1375. // TDescriptor::AddData: 
  1376. //----------------------------------------------------------------------------------------
  1377. void TDescriptor::AddData(DescType descType, Ptr data, Size length)
  1378.     {
  1379.     this->AddData(0,descType,data,length);
  1380.     } // TDescriptor::AddData 
  1381.  
  1382. //----------------------------------------------------------------------------------------
  1383. // TDescriptor::AddLong: 
  1384. //----------------------------------------------------------------------------------------
  1385. void TDescriptor::AddLong(long number)
  1386.     {
  1387.     this->AddData(typeLongInteger,(Ptr)&number,sizeof(long));
  1388.     } // TDescriptor::AddLong 
  1389.  
  1390. //----------------------------------------------------------------------------------------
  1391. // TDescriptor::AddType: 
  1392. //----------------------------------------------------------------------------------------
  1393. void TDescriptor::AddType(DescType descType)
  1394.     {
  1395.     this->AddData(typeType,(Ptr)&descType,sizeof(DescType));
  1396.     } // TDescriptor::AddType 
  1397.  
  1398. //----------------------------------------------------------------------------------------
  1399. // TDescriptor::AppendList:
  1400. //
  1401. // Append a list onto the end of this one.  The list passed in may be a null descriptor
  1402. // or a single item as well as a list.
  1403. //----------------------------------------------------------------------------------------
  1404. void TDescriptor::AppendList(const TDescriptor& list)
  1405.     {
  1406.     TDescriptor descriptor;
  1407.     OSErr err = noErr;
  1408.     
  1409.     //
  1410.     // If this descriptor is a null descriptor, then we just want
  1411.     // to copy the incoming list.
  1412.     //
  1413.     // In the past we did not do this check, which resulted in
  1414.     // the unfortunate side effect of converting a single-item
  1415.     // list into a single (non-list) descriptor whenever said
  1416.     // list was 'AppendList'ed into an empty list.  While this
  1417.     // may be more efficient, it really hosed us over in the case
  1418.     // of GetData on the selection property, which is SUPPOSED
  1419.     // to return a single-item list (as opposed to a single
  1420.     // descriptor) if there is only one item in the list.  (This
  1421.     // is quite different from most other objects, which are
  1422.     // supposed to return single descriptors instead of single-
  1423.     // item lists whenever there is only one object in the result.)
  1424.     //
  1425.     if(this->IsNullDescriptor())
  1426.         {
  1427.         this->CopyDesc(list);
  1428.         }
  1429.     else if(list.IsNullDescriptor() == false) {
  1430.         try {
  1431.             FOREACHDESCRIPTOR(&list, descriptor)
  1432.                 {
  1433.                 this->AddDescriptor(descriptor);
  1434.                 }
  1435.             }
  1436.         catch( OSErr err )
  1437.             {
  1438.             descriptor.Dispose();
  1439.             throw(err);
  1440.             }
  1441.         }
  1442.     } // TDescriptor::AppendList 
  1443.  
  1444. //----------------------------------------------------------------------------------------
  1445. // TDescriptor::AdoptList: 
  1446. //----------------------------------------------------------------------------------------
  1447. void TDescriptor::AdoptList(TDescriptor* list)
  1448.     {
  1449.     if(this->IsNullDescriptor())
  1450.         {
  1451.         this->AdoptDesc(*list);
  1452.         }
  1453.     else
  1454.         {
  1455.         this->AppendList(*list);
  1456.         list->Dispose();
  1457.         }
  1458.     } // TDescriptor::AdoptList 
  1459.  
  1460. //----------------------------------------------------------------------------------------
  1461. // TDescriptor::MakeAERecord:
  1462. //
  1463. // CreateList creates both AERecords and AELists.
  1464. //----------------------------------------------------------------------------------------
  1465. void TDescriptor::MakeAERecord()
  1466.     {
  1467.     this->CreateList(kMakeAERecord);
  1468.     } // TDescriptor::MakeAERecord 
  1469.     
  1470. //----------------------------------------------------------------------------------------
  1471. // TDescriptor::GetDescriptor:
  1472. //
  1473. // Get the ae descriptor from the event. If the desired type is not specified, it
  1474. // defaults to typeWildCard
  1475. //----------------------------------------------------------------------------------------
  1476. TDescriptor TDescriptor::GetDescriptor(AEKeyword key, DescType desiredType)
  1477.     {
  1478.     TDescriptor result;
  1479.  
  1480.     //
  1481.     // n.b. This object must be typeAERecord or typeAppleEvent, or this
  1482.     // call will fail.  Other record-like descriptors (e.g. object specifiers)
  1483.     // cannot be passed to AEGetParamDesc.
  1484.     //
  1485.     FailErr(AEGetParamDesc(*this, key, desiredType, (AEDesc *) &result));
  1486.     
  1487.     return result;
  1488.     } // TDescriptor::GetDescriptor 
  1489.     
  1490. //----------------------------------------------------------------------------------------
  1491. // TDescriptor::GetOptionalParameter:
  1492. //
  1493. // Like 'GetDescriptor, but returns a null descriptor if the specified parameter could not
  1494. // be extracted.
  1495. //----------------------------------------------------------------------------------------
  1496. TDescriptor TDescriptor::GetOptionalParameter(AEKeyword key, DescType desiredType)
  1497.     {
  1498.     TDescriptor result;
  1499.     OSErr err = noErr;
  1500.  
  1501.     //
  1502.     // It's probably not necessary to call MakeNull if there is
  1503.     // an error, but we might as well be safe (paranoid?).
  1504.     //
  1505.     err = AEGetParamDesc(*this, key, desiredType, (AEDesc *) &result);
  1506.     if(err != noErr)
  1507.         result.MakeNull();
  1508.     
  1509.     return result;
  1510.     } // TDescriptor::GetOptionalParameter 
  1511.  
  1512. //----------------------------------------------------------------------------------------
  1513. // TDescriptor::GetParameterPtr:
  1514. //
  1515. // Get the ae descriptor from the record
  1516. //----------------------------------------------------------------------------------------
  1517. void TDescriptor::GetParameterPtr(AEKeyword key, DescType desiredType, DescType *typeCode, Ptr dataPtr, Size maximumSize, Size *actualSize)
  1518.     {
  1519.     //
  1520.     // n.b. This object must be typeAERecord or typeAppleEvent, or this
  1521.     // call will fail.  Other record-like descriptors (e.g. object specifiers)
  1522.     // cannot be passed to AEGetParamPtr.
  1523.     //
  1524.     FailErr(AEGetParamPtr(*this, key, desiredType, typeCode, dataPtr, maximumSize, actualSize));
  1525.     } // TDescriptor::GetParameterPtr 
  1526.     
  1527. //----------------------------------------------------------------------------------------
  1528. // TDescriptor::GetLongParameter:
  1529. //
  1530. // Get the first longword of data from a parameter coerced to the specified type
  1531. // (usually typeLongInteger)
  1532. //----------------------------------------------------------------------------------------
  1533. long TDescriptor::GetLongParameter(AEKeyword key, DescType desiredType)
  1534.     {
  1535.     long actualSize;
  1536.     DescType typeCode;
  1537.     long result = 0;
  1538.         
  1539.     GetParameterPtr(key, desiredType, &typeCode, (Ptr) &result, sizeof(long), &actualSize);
  1540.     
  1541.     return result;
  1542.     } // TDescriptor::GetLongParameter 
  1543.     
  1544. //----------------------------------------------------------------------------------------
  1545. // TDescriptor::GetShortParameter:
  1546. //
  1547. // Get the first shortword of data from a parameter coerced to the specified type
  1548. // (usually typeShortInteger)
  1549. //----------------------------------------------------------------------------------------
  1550. short TDescriptor::GetShortParameter(AEKeyword key, DescType desiredType)
  1551.     {
  1552.     long actualSize;
  1553.     DescType typeCode;
  1554.     short result = 0;
  1555.     GetParameterPtr(key, desiredType, &typeCode, (Ptr) &result, sizeof(short), &actualSize);
  1556.     
  1557.     return result;
  1558.     } // TDescriptor::GetShortParameter 
  1559.     
  1560. //----------------------------------------------------------------------------------------
  1561. // TDescriptor::GetDirectObject:
  1562. //
  1563. // Get the direct object of the event
  1564. //----------------------------------------------------------------------------------------
  1565. TDescriptor TDescriptor::GetDirectObject()
  1566.     {
  1567.     return GetDescriptor(keyDirectObject);
  1568.     } // TDescriptor::GetDirectObject 
  1569.  
  1570. //----------------------------------------------------------------------------------------
  1571. // TDescriptor::GetErrorCode:
  1572. //
  1573. // Get an error code
  1574. //----------------------------------------------------------------------------------------
  1575. long TDescriptor::GetErrorCode()
  1576.     {
  1577.     long error = noErr;
  1578.     
  1579.     try {
  1580.         error = GetLongParameter(keyErrorNumber);
  1581.     } catch( OSErr err ) {
  1582.         if( err != errAEDescNotFound )
  1583.             throw( err );
  1584.     }
  1585.     
  1586.     return( error );
  1587.     } // TDescriptor::GetErrorCode 
  1588.  
  1589. //----------------------------------------------------------------------------------------
  1590. // TDescriptor::PutDescriptor:
  1591. //
  1592. // Put a TDescriptor into the event
  1593. //----------------------------------------------------------------------------------------
  1594. void TDescriptor::PutDescriptor(AEKeyword key, TDescriptor data)
  1595.     {
  1596.     FailErr(AEPutParamDesc(*this, key, data));
  1597.     } // TDescriptor::PutDescriptor 
  1598.     
  1599. //----------------------------------------------------------------------------------------
  1600. // TDescriptor::PutParameterPtr:
  1601. //
  1602. // Create a descriptor from a block of data and insert it into the record
  1603. //----------------------------------------------------------------------------------------
  1604. void TDescriptor::PutParameterPtr(AEKeyword key, DescType typeCode, Ptr dataPtr, Size dataSize)
  1605.     {
  1606.     FailErr(AEPutParamPtr(*this, key, typeCode, dataPtr, dataSize));
  1607.     } // TDescriptor::PutParameterPtr 
  1608.  
  1609. //----------------------------------------------------------------------------------------
  1610. // TDescriptor::PutParameterHandle: 
  1611. //----------------------------------------------------------------------------------------
  1612. void TDescriptor::PutParameterHandle(AEKeyword key, DescType typeCode, Handle dataHandle)
  1613.     {
  1614.     short        handleState;
  1615.     Size        dataSize;
  1616.     
  1617.     //
  1618.     // Feature:  if the dataHandle is nil, nothing is added to the AERecord.
  1619.     //
  1620.     if(dataHandle != nil)
  1621.         {
  1622.         handleState = HGetState(dataHandle);
  1623.         HLock(dataHandle);
  1624.         dataSize = GetHandleSize(dataHandle);
  1625.         
  1626.         this->PutParameterPtr(key,typeCode,*dataHandle,dataSize);
  1627.         
  1628.         HSetState(dataHandle,handleState);
  1629.         }
  1630.     } // TDescriptor::PutParameterHandle 
  1631.     
  1632. //----------------------------------------------------------------------------------------
  1633. // TDescriptor::PutLongParameter:
  1634. //
  1635. // Put a long parameter (type specified)
  1636. //----------------------------------------------------------------------------------------
  1637. void TDescriptor::PutLongParameter(AEKeyword key, DescType typeCode, long data)
  1638.     {
  1639.     this->PutParameterPtr(key, typeCode, (Ptr) &data, sizeof(long));
  1640.     } // TDescriptor::PutLongParameter 
  1641.     
  1642. //----------------------------------------------------------------------------------------
  1643. // TDescriptor::PutLongParameter:
  1644. //
  1645. // Put a long parameter (type is 'typeLongInteger', the most common case)
  1646. //----------------------------------------------------------------------------------------
  1647. void TDescriptor::PutLongParameter(AEKeyword key, long data)
  1648.     {
  1649.     this->PutLongParameter(key,typeLongInteger,data);
  1650.     } // TDescriptor::PutLongParameter 
  1651.     
  1652. //----------------------------------------------------------------------------------------
  1653. // TDescriptor::PutShortParameter:
  1654. //
  1655. // Put a short parameter (type specified)
  1656. //----------------------------------------------------------------------------------------
  1657. void TDescriptor::PutShortParameter(AEKeyword key, DescType typeCode, short data)
  1658.     {
  1659.     this->PutParameterPtr(key, typeCode, (Ptr) &data, sizeof(short));
  1660.     } // TDescriptor::PutShortParameter 
  1661.     
  1662. //----------------------------------------------------------------------------------------
  1663. // TDescriptor::PutShortParameter:
  1664. //
  1665. // Put a short parameter (type is 'typeShortInteger', the most common case)
  1666. //----------------------------------------------------------------------------------------
  1667. void TDescriptor::PutShortParameter(AEKeyword key, short data)
  1668.     {
  1669.     this->PutShortParameter(key,typeShortInteger,data);
  1670.     } // TDescriptor::PutShortParameter 
  1671.  
  1672. //----------------------------------------------------------------------------------------
  1673. // TDescriptor::PutResult: 
  1674. //
  1675. // Put the provided descriptor into the result parameter of this event.  If the data
  1676. // is a null descriptor, then put in an empty list instead.
  1677. //----------------------------------------------------------------------------------------
  1678. void TDescriptor::PutResult(TDescriptor data)
  1679.     {
  1680.     OSErr err = noErr;
  1681.     
  1682.     //
  1683.     // If there's nothing in the data, then insert an empty list.
  1684.     //
  1685.     if(data.IsNullDescriptor())
  1686.         {
  1687.         TDescriptor emptyList;
  1688.  
  1689.         try {
  1690.             emptyList.MakeEmptyList();
  1691.             this->PutDescriptor(keyAEResult, emptyList);
  1692.             emptyList.Dispose();
  1693.             }
  1694.         catch( OSErr err )
  1695.             {
  1696.             emptyList.Dispose();
  1697.             throw(err);
  1698.             }
  1699.         }
  1700.     else
  1701.         {
  1702.         this->PutDescriptor(keyAEResult,data);
  1703.         }
  1704.     } // TDescriptor::PutResult 
  1705.     
  1706. //----------------------------------------------------------------------------------------
  1707. // TDescriptor::PutErrorCode:
  1708. //
  1709. // Put an error code
  1710. //----------------------------------------------------------------------------------------
  1711. void TDescriptor::PutErrorCode(long theErr)
  1712.     {
  1713.     this->PutLongParameter(keyErrorNumber,theErr);
  1714.     } // TDescriptor::PutErrorCode 
  1715.  
  1716. //----------------------------------------------------------------------------------------
  1717. // TDescriptor::Resolve: 
  1718. //----------------------------------------------------------------------------------------
  1719. TTokenDescriptor TDescriptor::Resolve()
  1720.     {
  1721.     return TDescriptor::Resolve(fCallbackFlags);
  1722.     } // TDescriptor::Resolve 
  1723.  
  1724. //----------------------------------------------------------------------------------------
  1725. // TDescriptor::Resolve:
  1726. //
  1727. // Resolves a list of object specifiers into a list of tokens.  A null descriptor will
  1728. // resolve to a token to the null container.
  1729. //
  1730. // n.b. AEResolve will return an error if you pass it a null descriptor; this is why
  1731. //        we include 'magic' checking for null descriptors here.
  1732. //----------------------------------------------------------------------------------------
  1733. TTokenDescriptor TDescriptor::Resolve(short callbackFlags)
  1734.     {
  1735.     TTokenDescriptor resolvedToken;
  1736.     TTokenDescriptor intermediate;
  1737.     TDescriptor descriptor;
  1738.     
  1739.     //
  1740.     // First:  special checking for null descriptors
  1741.     //
  1742.     if(this->IsNullDescriptor())
  1743.         {
  1744.         resolvedToken = CreateNullContainerToken();
  1745.         }
  1746.     //
  1747.     // Next, process non-lists
  1748.     //
  1749.     else if(this->DescriptorType() != typeAEList)
  1750.         {
  1751.         //
  1752.         // If a pre-resolve proc was installed, then call it.
  1753.         //
  1754.         // The Scriptable Finder uses this for resolving token
  1755.         // types that AEResolve does not recognize (e.g. alias
  1756.         // records)
  1757.         //
  1758.         if(gPreResolveProc != nil)
  1759.             {
  1760.             resolvedToken = (*gPreResolveProc)(*this);
  1761.             }
  1762.  
  1763.         //
  1764.         // If the pre-resolve proc did not resolve the token,
  1765.         // then call AEResolve
  1766.         //
  1767.         if(resolvedToken.IsNullDescriptor())
  1768.             FailErr(AEResolve(*this, callbackFlags, resolvedToken));
  1769.         }
  1770.     //
  1771.     // If we have a list, try to resolve each element of the list in turn
  1772.     //
  1773.     else
  1774.         {
  1775.         OSErr err = noErr;
  1776.         
  1777.         try {
  1778.             FOREACHDESCRIPTOR(this, descriptor)
  1779.                 {
  1780.                 //
  1781.                 // We do not want to dispose of the intermediate token descriptor
  1782.                 // because its data is adopted by the 'result' token descriptor.
  1783.                 //
  1784.                 intermediate = descriptor.Resolve(callbackFlags);
  1785.                 resolvedToken.AdoptToken(intermediate);
  1786.                 intermediate.MakeNull();
  1787.                 }
  1788.             }
  1789.         catch( OSErr err )
  1790.             {
  1791.             descriptor.Dispose();
  1792.             intermediate.DisposeToken();
  1793.             resolvedToken.DisposeToken();
  1794.             throw(err);
  1795.             }
  1796.         }
  1797.     
  1798.     return resolvedToken;
  1799.     } // TDescriptor::Resolve 
  1800.  
  1801.  
  1802. //========================================================================================
  1803. // CLASS TAEvent
  1804. //
  1805. // AppleEvents are just like AERecords, but they can contain attributes as well as
  1806. // parameters.
  1807. //========================================================================================
  1808.  
  1809.  
  1810. //----------------------------------------------------------------------------------------
  1811. // TAEvent::TAEvent: 
  1812. //----------------------------------------------------------------------------------------
  1813. TAEvent::TAEvent()
  1814.     {
  1815.  
  1816.     } // TAEvent::TAEvent 
  1817.  
  1818. //----------------------------------------------------------------------------------------
  1819. // TAEvent::TAEvent: 
  1820. //----------------------------------------------------------------------------------------
  1821. TAEvent::TAEvent(
  1822.             AEEventClass    eventClass,
  1823.             AEEventID        eventID,
  1824.             OSType            target,
  1825.     const    char            *format,
  1826.     const    void            *args )
  1827. {
  1828.     FailErr( vAEBuildAppleEvent( eventClass, eventID,
  1829.                                 typeApplSignature, &target, sizeof( target ),
  1830.                                 kAutoGenerateReturnID, kAnyTransactionID,
  1831.                                 (AppleEvent*) this, format, args ) );
  1832. }
  1833.  
  1834. //----------------------------------------------------------------------------------------
  1835. // TAEvent::TAEvent: 
  1836. //----------------------------------------------------------------------------------------
  1837. TAEvent::TAEvent(
  1838.             AEEventClass    eventClass,
  1839.             AEEventID        eventID,
  1840.             OSType            target,
  1841.     const    char            *format,
  1842.             ... )
  1843. {
  1844.     va_list    args;
  1845.     va_start( args, format );
  1846.     
  1847.     FailErr( vAEBuildAppleEvent( eventClass, eventID,
  1848.                                 typeApplSignature, &target, sizeof( target ),
  1849.                                 kAutoGenerateReturnID, kAnyTransactionID,
  1850.                                 (AppleEvent*) this, format, args ) );
  1851.     
  1852.     va_end( args );
  1853. }
  1854.  
  1855. //----------------------------------------------------------------------------------------
  1856. // TAEvent::MakeAppleEvent: 
  1857. //----------------------------------------------------------------------------------------
  1858. void TAEvent::MakeAppleEvent(AEEventClass eventClass, AEEventID eventID,
  1859.                         const TDescriptor& target, short returnID, long transactionID)
  1860.     {
  1861.     FailErr(AECreateAppleEvent(eventClass, eventID,
  1862.                         (const AEAddressDesc *) &target, returnID, transactionID, *this));
  1863.     } // TAEvent::MakeAppleEvent 
  1864.  
  1865. //----------------------------------------------------------------------------------------
  1866. // TAEvent::MakeAppleEvent: 
  1867. //----------------------------------------------------------------------------------------
  1868. void TAEvent::MakeAppleEvent(AEEventClass eventClass, AEEventID eventID,
  1869.                         const ProcessSerialNumber& psn, short returnID, long transactionID)
  1870.     {
  1871.     TDescriptor address;
  1872.     address.CopyData(typeProcessSerialNumber, (Ptr) &psn, sizeof(ProcessSerialNumber));
  1873.     
  1874.     this->MakeAppleEvent(eventClass, eventID, address, returnID, transactionID);
  1875.     
  1876.     address.Dispose();
  1877.     } // TAEvent::MakeAppleEvent 
  1878.  
  1879.  
  1880. #define kCheckAEM            0
  1881. #define kDontUseSelfSend    1
  1882. #define kSelfSendSafe        2
  1883.  
  1884. short gCanUseSelfSend = kCheckAEM;
  1885.  
  1886. //----------------------------------------------------------------------------------------
  1887. // TAEvent::MakeEventAddressedToSelf: 
  1888. //----------------------------------------------------------------------------------------
  1889. void TAEvent::MakeEventAddressedToSelf(AEEventClass eventClass, AEEventID eventID, short returnID, long transactionID)
  1890.     {
  1891.     ProcessSerialNumber current;        // create psn for the Finder
  1892.     current.highLongOfPSN = 0;
  1893.     current.lowLongOfPSN = kCurrentProcess;
  1894.     
  1895.     //
  1896.     // Old versions of the AEM leak memory if send-to-self is used
  1897.     //
  1898.     if(gCanUseSelfSend == kCheckAEM)
  1899.         {
  1900.         long aevtSelector = 0;
  1901.         OSErr err = Gestalt('evnt', &aevtSelector);
  1902.         gCanUseSelfSend = ((aevtSelector & 2) != 0) ? kSelfSendSafe : kDontUseSelfSend;
  1903.         }
  1904.     
  1905.     //
  1906.     // Don't make the self-addressed event unless it is safe to do so
  1907.     //
  1908.     if(gCanUseSelfSend == kSelfSendSafe)
  1909.         {
  1910.         this->MakeAppleEvent(eventClass, eventID, current, returnID, transactionID);
  1911.         }
  1912.     else
  1913.         FailErr(errAEEventNotHandled);
  1914.     } // TAEvent::MakeEventAddressedToSelf 
  1915.  
  1916. //----------------------------------------------------------------------------------------
  1917. // TAEvent::MakeEventAddressedToSystem: 
  1918. //----------------------------------------------------------------------------------------
  1919. void TAEvent::MakeEventAddressedToSystem(AEEventClass eventClass, AEEventID eventID, short returnID, long transactionID)
  1920.     {
  1921.     ProcessSerialNumber systemPSN;        // create psn for the System
  1922.     systemPSN.highLongOfPSN = 0;
  1923.     systemPSN.lowLongOfPSN = kSystemProcess;
  1924.     
  1925.     this->MakeAppleEvent(eventClass, eventID, systemPSN, returnID, transactionID);
  1926.     } // TAEvent::MakeEventAddressedToSystem 
  1927.  
  1928. //----------------------------------------------------------------------------------------
  1929. // TAEvent::Send: 
  1930. //----------------------------------------------------------------------------------------
  1931. void TAEvent::Send( TAEvent* reply,
  1932.                     AESendMode sendMode,
  1933.                     AESendPriority sendPriority,
  1934.                     long timeOutInTicks,
  1935.                     AEIdleUPP idleProc,
  1936.                     AEFilterUPP filterProc)
  1937.     {
  1938.     OSErr err = AESend(*this, *reply, sendMode, sendPriority, timeOutInTicks, idleProc, filterProc);\
  1939.     if((err != errAETimeout) || (timeOutInTicks != 0))
  1940.         FailErr(err);
  1941.     } // TAEvent::Send 
  1942.  
  1943. //----------------------------------------------------------------------------------------
  1944. // TAEvent::Ask
  1945. //
  1946. // Ask a question using future semantics--i.e., send kAEWaitReply with a timeout of 0,
  1947. // then set the reply timeout using the API provided by the futures package.
  1948. //----------------------------------------------------------------------------------------
  1949. TAEvent TAEvent::Ask(long timeoutValue /* = 1200 */, long maxWaitTime /* = 0x7FFFFFFF */, AESendPriority sendPriority /* = kAENormalPriority */)
  1950.     {
  1951.     TAEvent reply;
  1952.     
  1953.     FailErr(AskForFuture(*this, reply, timeoutValue, maxWaitTime, sendPriority));
  1954.     
  1955.     return reply;
  1956.     }
  1957.  
  1958. #define kAEDontExecute 0x2000 // for SendMode, when you just want an event recorded, not executed
  1959.  
  1960. //----------------------------------------------------------------------------------------
  1961. // TAEvent::SendNoExecute: 
  1962. //
  1963. // This routine sends the event with the 'kAEDontExecute' bit set, so that the
  1964. // event will be recorded, but the recipient will not execute it.  The event is
  1965. // also sent 'no reply', since it does not make sense to expect a result from
  1966. // a command that is not actually executed.
  1967. //----------------------------------------------------------------------------------------
  1968. void TAEvent::SendNoExecute()
  1969.     {
  1970.     //
  1971.     // The reply isn't actuall filled in due to the kAENoReply flag
  1972.     //
  1973.     TAEvent reply;
  1974.     Send(&reply, kAENoReply+kAEDontExecute);
  1975.     } // TAEvent::SendNoExecute 
  1976.  
  1977.  
  1978. //----------------------------------------------------------------------------------------
  1979. // TAEvent::SuspendTheCurrentEvent: 
  1980. //----------------------------------------------------------------------------------------
  1981. void TAEvent::SuspendTheCurrentEvent()
  1982.     {
  1983.     FailErr(AESuspendTheCurrentEvent(*this));
  1984.     } // TAEvent::SuspendTheCurrentEvent 
  1985.  
  1986. //----------------------------------------------------------------------------------------
  1987. // TAEvent::ResumeTheCurrentEvent: 
  1988. //----------------------------------------------------------------------------------------
  1989. void TAEvent::ResumeTheCurrentEvent(TAEvent* reply, AEEventHandlerUPP dispatcher, long refCon)
  1990.     {
  1991.     FailErr(AEResumeTheCurrentEvent(*this, *reply, dispatcher, refCon));
  1992.     } // TAEvent::ResumeTheCurrentEvent 
  1993.  
  1994. //----------------------------------------------------------------------------------------
  1995. // TAEvent::SetTheCurrentEvent: 
  1996. //----------------------------------------------------------------------------------------
  1997. void TAEvent::SetTheCurrentEvent()
  1998.     {
  1999.     FailErr(AESetTheCurrentEvent(*this));
  2000.     } // TAEvent::SetTheCurrentEvent 
  2001.  
  2002. //----------------------------------------------------------------------------------------
  2003. // TAEvent::ResetTimer: 
  2004. //
  2005. // Note:    requires that this event be a 'reply' event passed to one of our event
  2006. //            handlers by the AppleEvent manager 
  2007. //----------------------------------------------------------------------------------------
  2008. void TAEvent::ResetTimer()
  2009.     {
  2010.     FailErr(AEResetTimer(*this));
  2011.     } // TAEvent::ResetTimer 
  2012.  
  2013. //----------------------------------------------------------------------------------------
  2014. // TAEvent::SpecifyThatParameterIsOptional: 
  2015. //----------------------------------------------------------------------------------------
  2016. void TAEvent::SpecifyThatParameterIsOptional(AEKeyword theOptionalKeyword)
  2017.     {
  2018.     TDescriptor optionalKeywordsList;
  2019.     TDescriptor optionalKeyword;
  2020.     OSErr err = noErr;
  2021.     
  2022.     try {
  2023.         //
  2024.         // ◊Script:  We need to test to see if keyOptionalKeywordAttr
  2025.         // already exists, and if so, then just add one more element to
  2026.         // the list that is already inside the event.
  2027.         //
  2028.         optionalKeywordsList.MakeList();
  2029.         optionalKeyword.MakeKeyword(theOptionalKeyword);
  2030.         optionalKeywordsList.AddDescriptor(optionalKeyword);
  2031.         optionalKeyword.Dispose();
  2032.         this->PutAttribute(keyOptionalKeywordAttr, optionalKeywordsList);
  2033.         optionalKeywordsList.Dispose();
  2034.         }
  2035.     catch( OSErr err )
  2036.         {
  2037.         optionalKeyword.Dispose();
  2038.         optionalKeywordsList.Dispose();
  2039.         
  2040.         throw(err);
  2041.         }
  2042.     } // TAEvent::SpecifyThatParameterIsOptional 
  2043.  
  2044. //----------------------------------------------------------------------------------------
  2045. // TAEvent::GetAttribute: 
  2046. //----------------------------------------------------------------------------------------
  2047. TDescriptor TAEvent::GetAttribute(AEKeyword key, DescType desiredType /* = typeWildCard */)
  2048.     {
  2049.     TDescriptor result;
  2050.     
  2051.     FailErr(AEGetAttributeDesc(*this, key, desiredType, result));
  2052.     
  2053.     return result;
  2054.     } // TAEvent::GetAttribute 
  2055.  
  2056. //----------------------------------------------------------------------------------------
  2057. // TAEvent::GetLongAttribute: 
  2058. //----------------------------------------------------------------------------------------
  2059. long TAEvent::GetLongAttribute(AEKeyword key)
  2060.     {
  2061.     DescType typeCode;
  2062.     long actualSize;
  2063.     long result;
  2064.     
  2065.     FailErr(AEGetAttributePtr(*this, key, typeLongInteger, &typeCode, (Ptr)&result, sizeof(long), &actualSize));
  2066.     
  2067.     return result;
  2068.     } // TAEvent::GetLongAttribute 
  2069.  
  2070. /****************************************************************************************
  2071.     Commenter    Date                Comment
  2072.     ---------    -----------------    -----------------------------------------------------
  2073.     wolf        Tue, Apr 7, 1998    Created.
  2074.     
  2075.     ************************************************************************************/
  2076.  
  2077.     DescType
  2078. TAEvent::GetTypeAttribute(
  2079.     AEKeyword    key )
  2080. {
  2081.     DescType    typeCode;
  2082.     long        actualSize;
  2083.     DescType    result;
  2084.     
  2085.     FailErr( AEGetAttributePtr( *this, key, typeType, &typeCode, &result, sizeof(result), &actualSize ) );
  2086.     
  2087.     return( result );
  2088. }
  2089.  
  2090. //----------------------------------------------------------------------------------------
  2091. // TAEvent::PutAttribute: 
  2092. //----------------------------------------------------------------------------------------
  2093. void TAEvent::PutAttribute(AEKeyword key, TDescriptor attribute)
  2094.     {
  2095.     FailErr(AEPutAttributeDesc(*this, key, attribute));
  2096.     } // TAEvent::PutAttribute 
  2097.  
  2098. //----------------------------------------------------------------------------------------
  2099. // PutOptionalDescriptor: 
  2100. //----------------------------------------------------------------------------------------
  2101. void TAEvent::PutOptionalDescriptor(AEKeyword key, TDescriptor data)
  2102.     {
  2103.     this->PutDescriptor(key, data);
  2104.     this->SpecifyThatParameterIsOptional(key);
  2105.     } // TAEvent::PutOptionalDescriptor 
  2106.  
  2107. //----------------------------------------------------------------------------------------
  2108. // TAEvent::PutLongAttribute: 
  2109. //----------------------------------------------------------------------------------------
  2110. void TAEvent::PutLongAttribute(AEKeyword key, long attributeValue)
  2111.     {
  2112.     FailErr(AEPutAttributePtr(*this, key, typeLongInteger, (Ptr)&attributeValue, sizeof(long)));
  2113.     } // TAEvent::PutLongAttribute 
  2114.     
  2115.  
  2116. //========================================================================================
  2117. // CLASS TTokenDescriptor
  2118. //
  2119. // The class TTokenDescriptor represents descriptors returned by AEResolve
  2120. //========================================================================================
  2121.  
  2122.  
  2123. //----------------------------------------------------------------------------------------
  2124. // TTokenDescriptor::TTokenDescriptor: 
  2125. //----------------------------------------------------------------------------------------
  2126. TTokenDescriptor::TTokenDescriptor()
  2127.     {
  2128.     fDescriptorType = typeNull;
  2129.     fDataHandle = nil;
  2130.     } // TTokenDescriptor::TTokenDescriptor 
  2131.  
  2132. //----------------------------------------------------------------------------------------
  2133. // TTokenDescriptor::TTokenDescriptor: 
  2134. //----------------------------------------------------------------------------------------
  2135. TTokenDescriptor::TTokenDescriptor(TDescriptor desc)
  2136.     {
  2137.     this->fDescriptorType = desc.DescriptorType();
  2138.     this->fDataHandle = desc.DataHandle();
  2139.     } // TTokenDescriptor::TTokenDescriptor 
  2140.     
  2141. //----------------------------------------------------------------------------------------
  2142. // TTokenDescriptor::DisposeToken:
  2143. //
  2144. // It is very important that token descriptors be disposed of by AEDisposeToken,
  2145. // _not_ AEDisposeDesc.
  2146. //----------------------------------------------------------------------------------------
  2147. void TTokenDescriptor::DisposeToken()
  2148.     {
  2149.     AEDisposeToken(*this);  // Should fail on error?  Probably not.
  2150.  
  2151.     // FailErr(AEDisposeDesc(*this));
  2152.     } // TTokenDescriptor::DisposeToken 
  2153.  
  2154.  
  2155. //----------------------------------------------------------------------------------------
  2156. // TTokenDescriptor::TokenHandle:
  2157. //
  2158. // Return the TTokenObject stored inside the token descriptor
  2159. //----------------------------------------------------------------------------------------
  2160. TAbstractScriptableObject* TTokenDescriptor::TokenHandle()
  2161.     {
  2162.     Handle tokenHandle = this->DataHandle();
  2163.     TAbstractScriptableObject* tokenObject = nil;
  2164.     
  2165.     if((this->DescriptorType() != typeTokenObject) || (tokenHandle == nil))
  2166.         {
  2167.         //
  2168.         // ••• What error code should we fail with here?
  2169.         //
  2170.         FailErr(errAENoSuchObject);
  2171.         }
  2172.     
  2173.     //
  2174.     // tokenHandle is a handle that contains a TTokenObject*,
  2175.     // so it is a pointer to a pointer to a TTokenObject* (wow)
  2176.     //
  2177.     tokenObject = ** ((TAbstractScriptableObject***) tokenHandle);
  2178.     return tokenObject;
  2179.     } // TTokenDescriptor::TokenHandle 
  2180.  
  2181.  
  2182. //----------------------------------------------------------------------------------------
  2183. // TTokenDescriptor::AdoptToken:
  2184. //
  2185. // IMPORTANT: ADOPTS THE TOKEN PASSED TO IT
  2186. //----------------------------------------------------------------------------------------
  2187. void TTokenDescriptor::AdoptToken(TTokenDescriptor& tokenDescriptor)
  2188.     {
  2189.     //
  2190.     // Don't adopt the new token if it is empty
  2191.     //
  2192.     if(tokenDescriptor.IsNullDescriptor() == false)
  2193.         {
  2194.         //
  2195.         // If this descriptor is empty, it is easy to adopt the new token
  2196.         //
  2197.         if( this->IsNullDescriptor() )
  2198.             {
  2199.             TDescriptor::AdoptHandle(tokenDescriptor.DescriptorType(), tokenDescriptor.DataHandle() );
  2200.             tokenDescriptor.MakeNull();
  2201.             }
  2202.         else
  2203.             {
  2204.             TAbstractScriptableObject* tokenObject = tokenDescriptor.TokenHandle();
  2205.             this->AdoptToken(tokenObject);
  2206.             
  2207.             //
  2208.             // n.b.    'Dispose', not 'DisposeToken'.  The token that
  2209.             // was formerly contained in tokenDescriptor is now referenced
  2210.             // in 'this' token descriptor, so it would be a bad idea to
  2211.             // delete it.
  2212.             //
  2213.             tokenDescriptor.Dispose();
  2214.             }
  2215.         }
  2216.     } // TTokenDescriptor::AdoptToken 
  2217.  
  2218. //----------------------------------------------------------------------------------------
  2219. // TTokenDescriptor::AdoptToken: 
  2220. //----------------------------------------------------------------------------------------
  2221. void TTokenDescriptor::AdoptToken(TAbstractScriptableObject* tokenObject)
  2222.     {
  2223.     //
  2224.     // Don't adopt the new token if it is not a valid object
  2225.     //
  2226.     if(tokenObject != nil)
  2227.         {
  2228.         //
  2229.         // If this descriptor is empty, then create a new
  2230.         // token descriptor to hold a pointer to the tokenObject.
  2231.         //
  2232.         if(this->IsNullDescriptor() )
  2233.             {
  2234.             Handle newHandle = NewHandle( sizeof(Ptr) );
  2235.             ** ((TAbstractScriptableObject***)newHandle) = tokenObject;
  2236.             
  2237.             TDescriptor::AdoptHandle(typeTokenObject, newHandle);
  2238.             }
  2239.         //
  2240.         // If there is already something here, then we need
  2241.         // to somehow merge the two tokens together.  In the
  2242.         // Scriptable Finder, we want to create a mark token
  2243.         // to do the merge.  However, MoreAEM does not depend
  2244.         // on files such as MarkToken.h which are outside of
  2245.         // the Blue folder.  Therefore, we call a callback proc
  2246.         // to fill in the mark token.  The callback proc is
  2247.         // installed in InitializeScriptability.
  2248.         //
  2249.         else
  2250.             {
  2251.             if(gMergeTokensProc == nil)
  2252.                 FailErr(errAEEventNotHandled);
  2253.                 
  2254.             //
  2255.             // The MergeTokensProc takes two TAbstractScriptableObject*'s
  2256.             // and merges them into another TAbstractScriptableObject*
  2257.             // (which adopts the two original tokens).
  2258.             //
  2259.             TAbstractScriptableObject* mergedTokens = (*gMergeTokensProc)(this->TokenHandle(), tokenObject);
  2260.  
  2261.             Handle tokenHandle = this->DataHandle();
  2262.             ** ((TAbstractScriptableObject***) tokenHandle) = mergedTokens;
  2263.             }
  2264.         }
  2265.     } // TTokenDescriptor::AdoptToken